// FMemoryManager.cpp (c) 2011 JV Software
//

#include "EnginePrivate.h"

static FArray<FMemoryNode>		nodes;

/*
=================
FMemoryManager::Init
=================
*/
void FMemoryManager::Init( void ) {
	engine->Printf(TEXT("FMemoryManager::Init: Init Memory...\n"));

	if(nodes.size() > 0) {
		engine->FatalError( TEXT("MemoryManager: Init called when there are active memory nodes!"));
		return;
	}

	memPoolSize = 0;
}

/*
===============
FMemoryManager::ReserveMemory
===============
*/
bool FMemoryManager::ReserveMemory( int size ) {
	if(!allowMemoryModification && forceAllowMemoryModification == false) {
		return false;
	}

	lastNodeSize = size;
	memPoolSize += size;

	allowMemoryModification = false;

	return true;
}

/*
===============
FMemoryManager::AppendNode
===============
*/
void FMemoryManager::AppendNode( FMemoryNode &node ) {
	node.nodeNum = nodes.size();
	node.nodeMemorySize = lastNodeSize;
	nodes.Append( node );
	nodes[node.nodeNum].nodePtr = &nodes[node.nodeNum];
	memset(((byte *)nodes[node.nodeNum].ptr - 4),node.nodeNum, sizeof( int ) );
}

/*
===============
FMemoryManager::FreeMemoryObject
===============
*/
void FMemoryManager::FreeMemoryObject( FObject *ptr ) {
	FMemoryNode		*node = &nodes[ptr->nodeNum];

	allowMemoryModification = true;

	// Free the node pointer.
	if(node->zoneType < FMEMORY_ZONE_TEMPBUFFER) {
		node->ptr->Destroy();
		
		// Delete the node pointer.
		delete node->ptr;
	}
	else {
		// Delete the node pointer.
		delete ((byte *)node->ptr);
	}
	
	// Reset the node pointer.
	node->nodePtr = NULL;

	// Remove the node from our list.
	nodes.erase( nodes.begin() + node->nodeNum );
}